// "Copyright [2021] <Copyright Han>"
#include<algorithm>
#include "routing_adapter.h"
#include "cluster/basic/ai_sim.h"
#include "cluster/roce/RoceMsg_m.h"

namespace ai_sim {
Define_Module(RoutingAdapter);
void RoutingAdapter::handleMessage(omnetpp::cMessage *msg) {
    if (msg->arrivedOn("configuration_port")) {
        // 如果是来自configurator的消息,那么记录相关映射关系
        ACLMsg *a_pk = dynamic_cast<ACLMsg *>(msg);
        if (a_pk != nullptr) {
            int address = a_pk->getAddressInt();
            int netmask = a_pk->getNetmaskInt();
            int router_id_ = a_pk->getRouterId();
            int output_gate_id_ = a_pk->getOutportGateId();
            std::pair<int, int> outport_key = std::make_pair(router_id_, output_gate_id_);
            IpAddressMap[outport_key] = address;
            NetmaskMap[outport_key] = netmask;
            outputGateInterfaceMap[outport_key] = a_pk->getLocalId();
            EV<<"outputGateInterfaceMapIndex: ["<<outport_key.first<<", "<<outport_key.second<<", "<<a_pk->getLocalId()<<" ]"<<endl;
            inputGateInterfaceMap[std::make_pair(
                router_id_, a_pk->getInportGateId())] =
                a_pk->getLocalId();
            delete a_pk;
        } else {
            OUTPORTIDMsg *outport_index_msg = dynamic_cast<OUTPORTIDMsg *>(msg);
            if (outport_index_msg != nullptr) {
                outportIndexMap[std::make_pair(
                    outport_index_msg->getSwitchID(), outport_index_msg->getPortIndex())] =
                    outport_index_msg->getOutportGateId();
            }
            delete outport_index_msg;
        }
    } else {
        error("error msg kind on routing adapter");
    }
}

void RoutingAdapter::getACL(
    vector<ACLSingleEntry>& acl_vec, RouteVec route_vec, int router_id) {
    Enter_Method_Silent();
    for (auto routes : route_vec) {
        // if(std::find(valid_port_list.begin(), valid_port_list.end(), routes.outPort) !=
        //     valid_port_list.end() &&
        //     std::find(valid_port_list.begin(), valid_port_list.end(), routes.inPort) !=
        //     valid_port_list.end()) {
            ACLSingleEntry ase;
            std::pair<int, int> route_key = std::make_pair(router_id, routes.outPort);
            if (outputGateInterfaceMap.find(route_key) != outputGateInterfaceMap.end()) {
                ase.interfaceID =  outputGateInterfaceMap[route_key];
                // EV<<"LocateIndex: &"<<route_key.first<<", "<<route_key.second<<", "<<ase.interfaceID<<" &"<<endl;
            } else {
                std::cout << "required id " << router_id << "\n";
                std::cout << "It is " << getSimulation()->getModule(router_id)->getFullPath() << endl;
                error("No such route in adapter(outportIndexMap)");
            }
            ase.SourceAddressInt = routes.srcIdx;
            ase.DestAddress = routes.destIdx;
            if (IpAddressMap.find(route_key) != IpAddressMap.end()) {
                ase.NextHopAddress =  IpAddressMap[route_key];
            } else {
                error("No such route in adapter(IpAddressMap)");
            }
            ase.SourcePort =  routes.inPort;
            ase.priority = -1;
            ase.protocolID = -1;
            if (ase.interfaceID == 0) {
                // std::cout << "SourceAddress in ACL" << ase.SourceAddress << endl;
                std::cout << "Index" << router_id << endl;
                std::cout  << "DestAddress in ACL" <<  ase.DestAddress << endl;
                std::cout  << "NextHopAddress IDin ACL" << ase.NextHopAddress << endl;
                std::cout  << "NextHopAddress in ACL" <<
                    inet::Ipv4Address(ase.NextHopAddress) << endl;
                std::cout  << "SourcePort in ACL" <<  ase.SourcePort << endl;
                std::cout  << "interfaceID in ACL" <<  ase.interfaceID << endl;
                error("Stop in adapter");
            }
            acl_vec.push_back(ase);
        // }
    }
}
}

